<html>
 <head>
  <meta charset="UTF-8">
 </head>
 <body>
  <h1 data-lake-id="Lzzyg" id="Lzzyg"><span data-lake-id="u3e5454b5" id="u3e5454b5">典型回答</span></h1>
  <p data-lake-id="u8c0dd631" id="u8c0dd631"><br></p>
  <p data-lake-id="u632fb835" id="u632fb835"><span data-lake-id="u7d8b8b3a" id="u7d8b8b3a">在Java中，我们可以通过多种方式来创建对象，并且只要对象没有被回收我们都可以复用该对象。但是，我们创建出来的这些Java对象都是存在于JVM的堆内存中的。只有JVM处于运行状态的时候，这些对象才可能存在。一旦JVM停止运行，这些对象的状态也就随之而丢失了。</span></p>
  <p data-lake-id="u1a806cff" id="u1a806cff"><span data-lake-id="u3573349b" id="u3573349b">​</span><br></p>
  <p data-lake-id="u330ead73" id="u330ead73"><span data-lake-id="u8611787d" id="u8611787d">但是在真实的应用场景中，我们需要将这些对象持久化下来，并且能够在需要的时候把对象重新读取出来。Java的对象序列化可以帮助我们实现该功能。</span></p>
  <p data-lake-id="u5159d755" id="u5159d755"><span data-lake-id="u7d295f32" id="u7d295f32">​</span><br></p>
  <p data-lake-id="u0a982d75" id="u0a982d75"><span data-lake-id="u774516ad" id="u774516ad">对象序列化机制（object serialization）是Java语言内建的一种对象持久化方式，</span><strong><span data-lake-id="u54292dd7" id="u54292dd7">通过对象序列化，可以把对象的状态保存为字节数组，并且可以在有需要的时候将这个字节数组通过反序列化的方式再转换成对象。</span></strong><span data-lake-id="u02c74908" id="u02c74908">对象序列化可以很容易的在JVM中的活动对象和字节数组（流）之间进行转换。</span></p>
  <p data-lake-id="u720a0b0a" id="u720a0b0a"><span data-lake-id="uf08a01b0" id="uf08a01b0">​</span><br></p>
  <p data-lake-id="u67c20076" id="u67c20076"><span data-lake-id="ufad0b736" id="ufad0b736">所以序列化就是把Java对象序列化成字节数组的过程，反序列化就是把字节数组再转换成Java对象的过程。</span></p>
  <p data-lake-id="uf98f1eab" id="uf98f1eab"><br></p>
  <h1 data-lake-id="kGwQP" id="kGwQP"><span data-lake-id="u15adc479" id="u15adc479">扩展知识</span></h1>
  <p data-lake-id="uccbfb3bb" id="uccbfb3bb"><br></p>
  <h2 data-lake-id="fMdOe" id="fMdOe"><span data-lake-id="uf0057c2d" id="uf0057c2d">如何进行序列化和反序列化</span></h2>
  <p data-lake-id="uc1bf0391" id="uc1bf0391"><br></p>
  <p data-lake-id="u86aff3ad" id="u86aff3ad"><span data-lake-id="u8fa9147f" id="u8fa9147f">在Java中，只要一个类实现了java.io.Serializable接口，那么它就可以被序列化。这里先来一段代码：</span></p>
  <p data-lake-id="u074446f8" id="u074446f8"><span data-lake-id="u3852759b" id="u3852759b">​</span><br></p>
  <pre lang="java"><code>
package com.hollis;
import java.io.Serializable;
import java.util.Date;

/**
 * Created by hollis on 16/2/2.
 */
public class User implements Serializable{
    private String name;
    private int age;
    private Date birthday;
    private transient String gender;
    private static final long serialVersionUID = -6849794470754667710L;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public Date getBirthday() {
        return birthday;
    }

    public void setBirthday(Date birthday) {
        this.birthday = birthday;
    }

    public String getGender() {
        return gender;
    }

    public void setGender(String gender) {
        this.gender = gender;
    }

    @Override
    public String toString() {
        return "User{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", gender=" + gender +
                ", birthday=" + birthday +
                '}';
    }
}
</code></pre>
  <p data-lake-id="ua2e89382" id="ua2e89382"><br></p>
  <p data-lake-id="u6d1e83b9" id="u6d1e83b9"><span data-lake-id="u23dbf829" id="u23dbf829" class="lake-fontsize-12" style="color: rgb(51, 51, 51)">code 2 对User进行序列化及反序列化的Demo：</span></p>
  <p data-lake-id="u82b0339a" id="u82b0339a"><span data-lake-id="uadaa0584" id="uadaa0584" class="lake-fontsize-12" style="color: rgb(51, 51, 51)">​</span><br></p>
  <pre lang="java"><code>
package com.hollis;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils;
import java.io.*;
import java.util.Date;

/**
 * Created by hollis on 16/2/2.
 */
public class SerializableDemo {

    public static void main(String[] args) {
        //Initializes The Object
        User user = new User();
        user.setName("hollis");
        user.setGender("male");
        user.setAge(23);
        user.setBirthday(new Date());
        System.out.println(user);

        //Write Obj to File
        ObjectOutputStream oos = null;
        try {
            oos = new ObjectOutputStream(new FileOutputStream("tempFile"));
            oos.writeObject(user);
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            IOUtils.closeQuietly(oos);
        }

        //Read Obj from File
        File file = new File("tempFile");
        ObjectInputStream ois = null;
        try {
            ois = new ObjectInputStream(new FileInputStream(file));
            User newUser = (User) ois.readObject();
            System.out.println(newUser);
        } catch (IOException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } finally {
            IOUtils.closeQuietly(ois);
            try {
                FileUtils.forceDelete(file);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

    }
}
//output 
//User{name='hollis', age=23, gender=male, birthday=Tue Feb 02 17:37:38 CST 2016}
//User{name='hollis', age=23, gender=null, birthday=Tue Feb 02 17:37:38 CST 2016}
</code></pre>
  <p data-lake-id="u43ada0ba" id="u43ada0ba"><br></p>
  <p data-lake-id="u967d6fd9" id="u967d6fd9"><span data-lake-id="udf5a0940" id="udf5a0940" class="lake-fontsize-12">以下几个和序列化&amp;反序列化有关的知识点大家可以重点关注一下：</span></p>
  <p data-lake-id="u351c54e9" id="u351c54e9"><span data-lake-id="ufde32c52" id="ufde32c52" class="lake-fontsize-12">​</span><br></p>
  <p data-lake-id="u66fbc4bd" id="u66fbc4bd"><span data-lake-id="u89395d68" id="u89395d68">1、在Java中，只要一个类实现了java.io.Serializable接口，那么它就可以被序列化。</span></p>
  <p data-lake-id="ua9844dd8" id="ua9844dd8"><span data-lake-id="uf0fe2d87" id="uf0fe2d87">​</span><br></p>
  <p data-lake-id="u04d4dcf8" id="u04d4dcf8"><span data-lake-id="u84aadd70" id="u84aadd70">2、通过</span><span data-lake-id="ub12c8b53" id="ub12c8b53">ObjectOutputStream</span><span data-lake-id="ufff89dbd" id="ufff89dbd">和</span><span data-lake-id="u2f245308" id="u2f245308">ObjectInputStream</span><span data-lake-id="u19efae7e" id="u19efae7e">对对象进行序列化及反序列化</span></p>
  <p data-lake-id="ucbe93c97" id="ucbe93c97"><span data-lake-id="u17809233" id="u17809233">​</span><br></p>
  <p data-lake-id="uf099247e" id="uf099247e"><span data-lake-id="ube5d0bd5" id="ube5d0bd5">3、虚拟机是否允许反序列化，不仅取决于类路径和功能代码是否一致，一个非常重要的一点是两个类的序列化 ID 是否一致（就是</span><span data-lake-id="ue6a0b882" id="ue6a0b882"> </span><span data-lake-id="udf48c250" id="udf48c250">private static final long serialVersionUID</span><span data-lake-id="uc37ec435" id="uc37ec435">）</span></p>
  <p data-lake-id="uc05d8fa2" id="uc05d8fa2"><span data-lake-id="u6f2deec2" id="u6f2deec2">​</span><br></p>
  <p data-lake-id="u8fca253b" id="u8fca253b"><span data-lake-id="ue4971426" id="ue4971426">4、序列化并不保存静态变量。</span></p>
  <p data-lake-id="ub22ebb52" id="ub22ebb52"><span data-lake-id="u23c8a689" id="u23c8a689">​</span><br></p>
  <p data-lake-id="ue566cb4d" id="ue566cb4d"><span data-lake-id="ud97d7b8e" id="ud97d7b8e">5、要想将父类对象也序列化，就需要让父类也实现</span><span data-lake-id="u74c80288" id="u74c80288">Serializable</span><span data-lake-id="u744d80bd" id="u744d80bd"> </span><span data-lake-id="ua8a90769" id="ua8a90769">接口。</span></p>
  <p data-lake-id="uef789fd9" id="uef789fd9"><span data-lake-id="ud9d70d0a" id="ud9d70d0a">​</span><br></p>
  <p data-lake-id="ud5a5d792" id="ud5a5d792"><span data-lake-id="u6d2dd48a" id="u6d2dd48a">6、transient 关键字的作用是控制变量的序列化，在变量声明前加上该关键字，可以阻止该变量被序列化到文件中，在被反序列化后，transient 变量的值被设为初始值，如 int 型的是 0，对象型的是 null。</span></p>
  <p data-lake-id="u2d63c414" id="u2d63c414"><span data-lake-id="u9823e0b1" id="u9823e0b1">​</span><br></p>
  <p data-lake-id="u1cc2f6b3" id="u1cc2f6b3"><span data-lake-id="u9fb7a900" id="u9fb7a900">7、服务器端给客户端发送序列化对象数据，对象中有一些数据是敏感的，比如密码字符串等，希望对该密码字段在序列化时，进行加密，而客户端如果拥有解密的密钥，只有在客户端进行反序列化时，才可以对密码进行读取，这样可以一定程度保证序列化对象的数据安全。</span></p>
  <p data-lake-id="u8fd75b98" id="u8fd75b98"><span data-lake-id="u0a8df208" id="u0a8df208">​</span><br></p>
  <h3 data-lake-id="AkZBm" id="AkZBm"><span data-lake-id="u29446932" id="u29446932">未实现Serializable，可以序列化吗？</span></h3>
  <p data-lake-id="u60d32e91" id="u60d32e91"><br></p>
  <p data-lake-id="u51b2a3bf" id="u51b2a3bf"><span data-lake-id="ucb048ad1" id="ucb048ad1">如果使用Java原生的序列化机制（即通过 ObjectOutputStream 和 ObjectInputStream 类），则对象必须实现 Serializable 接口。如果对象没有实现这个接口，尝试原生序列化会抛出 NotSerializableException。 </span></p>
  <p data-lake-id="u0b9e6d1d" id="u0b9e6d1d"><span data-lake-id="u2fcbe5ae" id="u2fcbe5ae">​</span><br></p>
  <p data-lake-id="ua4ed71ac" id="ua4ed71ac"><span data-lake-id="uc983a0e6" id="uc983a0e6">对于像Jackson、Gson这样的JSON序列化库或用于XML的库（如JAXB），对象不需要实现 Serializable 接口。这些库使用反射机制来访问对象的字段，并将它们转换成JSON或XML格式。在这种情况下，对象的序列化与 Serializable 接口无关。 </span></p>
  <p data-lake-id="ub7efa0e7" id="ub7efa0e7"><span data-lake-id="u23945adf" id="u23945adf">​</span><br></p>
  <p data-lake-id="u40137d69" id="u40137d69"><span data-lake-id="uc05a567c" id="uc05a567c">​</span><br></p>
  <h2 data-lake-id="Ansiw" id="Ansiw"><span data-lake-id="uc5fc555f" id="uc5fc555f">Java的序列化原理</span></h2>
  <p data-lake-id="u99928196" id="u99928196"><br></p>
 </body>
</html>